package com.spring.springcloud.Elasticsearch;

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.FuzzyQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;

import java.io.IOException;

public class D_ES的条件查询 {
    public static void main(String[] args) throws IOException {

        //在 Elasticsearch  8.x的版本已过期
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
        );
        String sy = "user";//对此索引操作

//        全量查询(esClient, sy);
//        条件查询(esClient, sy);
//        分页_排序查询(esClient, sy);
//        查询自定字段(esClient, sy);
//        组合查询(esClient, sy);
//        范围查询(esClient, sy);
//        模糊查询(esClient, sy);
//        高亮查询(esClient, sy);
        聚合查询(esClient, sy);

        esClient.close();//关闭客户端
    }

    private static void 聚合查询(RestHighLevelClient esClient, String sy) throws IOException {
        //模糊查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        //查询条件
        SearchSourceBuilder query = new SearchSourceBuilder();

        AggregationBuilder ab =
                AggregationBuilders
                        .terms("ageGroup")
                        .field("age");//只能针对 keyword 的字段
//                        .max("maxAge")//最大值
//                        .field("age");//age字段
        query.aggregation(ab);
        request.source(query);

        访问且展示(esClient, request);
    }

    private static void 高亮查询(RestHighLevelClient esClient, String sy) throws IOException {
        //模糊查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        //查询条件
        SearchSourceBuilder query =
                new SearchSourceBuilder()
                        .query(QueryBuilders.termQuery("name","2"));

        //高亮显示
        HighlightBuilder hb = new HighlightBuilder();
        hb.preTags("<font color='red'>");
        hb.postTags("<font>");
        hb.field("name");
        query.highlighter(hb);

        request.source(query);


        访问且展示(esClient, request);
    }

    private static void 模糊查询(RestHighLevelClient esClient, String sy) throws IOException {
        //模糊查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //name 查询  2  可以误差 Fuzziness.ONE   一个字符
        FuzzyQueryBuilder name = QueryBuilders.fuzzyQuery("name", "2")
                .fuzziness(Fuzziness.ONE);

        builder.query(name);

        request.source(builder);

        访问且展示(esClient, request);
    }

    private static void 范围查询(RestHighLevelClient esClient, String sy) throws IOException {
        //范围查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //范围查询  针对  age
        RangeQueryBuilder age = QueryBuilders.rangeQuery("age");

//        age.gte(18);//>=
//        age.lte(22);//<=
        age.gt(17);//>
        age.lt(22);//<

        builder.query(age);

        request.source(builder);

        访问且展示(esClient, request);
    }

    private static void 组合查询(RestHighLevelClient esClient, String sy) throws IOException {
        //组合查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        SearchSourceBuilder builder = new SearchSourceBuilder();

        BoolQueryBuilder bq = QueryBuilders.boolQuery();

        //并且
//        bq.must(QueryBuilders.matchQuery("age",18));//满足 age是18
//        bq.must(QueryBuilders.matchQuery("name","三"));//满足 name 有 三
//        bq.mustNot(QueryBuilders.matchQuery("sex","女"));//mustNot  不满足 sex 是 女

        //或者
        bq.should(QueryBuilders.matchQuery("age",18));//满足 age是18
        bq.should(QueryBuilders.matchQuery("name","三"));//满足 name 有 三
        bq.should(QueryBuilders.matchQuery("sex","女"));//mustNot  不满足 sex 是 女


        builder.query(bq);

        request.source(builder);

        访问且展示(esClient, request);

    }

    private static void 查询自定字段(RestHighLevelClient esClient, String sy) throws IOException {
        //指定/包含 某些字段
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        SearchSourceBuilder query =
                new SearchSourceBuilder()
                        .query(QueryBuilders.matchAllQuery());

        String[] s1 = {"name"};
        String[] s2 = {};
        //s1: 包含    s2:排除此字段
        query.fetchSource(s1,s2);

        request.source(query);
        访问且展示(esClient, request);
    }

    private static void 分页_排序查询(RestHighLevelClient esClient, String sy) throws IOException {
        //分页_排序查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        SearchSourceBuilder query =
                new SearchSourceBuilder()
                        .query(QueryBuilders.matchAllQuery());
        query.from(0);//第几页  x+1
        query.size(5);//每页多少个
        query.sort("age", SortOrder.DESC);
        request.source(query);

        访问且展示(esClient, request);
    }

    private static void 条件查询(RestHighLevelClient esClient, String sy) throws IOException {
        //条件查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        SearchSourceBuilder query =
                new SearchSourceBuilder()
                        .query(QueryBuilders.termQuery("name","2"));
        request.source(query);

        访问且展示(esClient, request);
    }

    private static void 全量查询(RestHighLevelClient esClient, String sy) throws IOException {
        //全量查询
        SearchRequest request = new SearchRequest();
        request.indices(sy);
        SearchSourceBuilder query =
                new SearchSourceBuilder()
                        .query(QueryBuilders.matchAllQuery());
        request.source(query);

        访问且展示(esClient, request);
    }

    private static void 访问且展示(RestHighLevelClient esClient, SearchRequest request) throws IOException {
        SearchResponse search = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = search.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(search.getTook());
        System.out.println("-----------------------------------------");
        for (SearchHit hit : hits){
            System.out.println(hit.getSourceAsString());
        }
        System.out.println("-----------------------------------------");
    }

}
